package com.scale.service.voice.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.example.voice.vo.TaskProgressMessage;
import com.scale.service.voice.dto.WebSocketMessage;
import com.scale.service.voice.dto.ProgressUpdateData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.net.URI;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 语音任务WebSocket处理器 - 按用户管理连接
 * @author crp
 * @since 2025-01-26
 */
@Component
public class VoiceTaskWebSocketHandler extends TextWebSocketHandler {
    
    private static final Logger log = LoggerFactory.getLogger(VoiceTaskWebSocketHandler.class);
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    // 🔧 改为按用户管理WebSocket连接
    private final Map<String, WebSocketSession> userSessions = new ConcurrentHashMap<>();
    
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String userId = extractUserIdFromUri(session.getUri());
        
        // 🔧 清理无效会话（在添加新会话前）
        cleanupInactiveUserSessions();
        
        // 如果用户已有连接，先关闭旧连接
        WebSocketSession oldSession = userSessions.get(userId);
        if (oldSession != null && oldSession.isOpen()) {
            log.info("🔄 用户{}已有连接，关闭旧连接: {}", userId, oldSession.getId());
            oldSession.close();
        }
        
        userSessions.put(userId, session);
        log.info("✅ WebSocket连接已建立: userId={}, sessionId={}, 总用户连接数={}", 
            userId, session.getId(), userSessions.size());
        log.info("📍 URI: {}", session.getUri());
        log.info("📍 当前所有用户连接: {}", userSessions.keySet());
        log.info("🔧 会话详情: userId={}, 会话开启状态={}, sessionHashCode={}", 
            userId, session.isOpen(), session.hashCode());
        
        // 发送连接成功消息
        sendConnectionMessage(userId, "CONNECTED", "WebSocket连接成功");
    }
    
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String userId = extractUserIdFromUri(session.getUri());
        userSessions.remove(userId);
        log.info("❌ WebSocket连接已关闭: userId={}, sessionId={}, 状态={}, 剩余用户连接数={}", 
            userId, session.getId(), status, userSessions.size());
    }
    
    /**
     * 发送进度更新消息（按用户发送，包含taskId）
     */
    public void sendProgressUpdate(String taskId, String userId, TaskProgressMessage message) {
        try {
            // 构建标准化的进度数据
            ProgressUpdateData progressData = new ProgressUpdateData();
            if (message.getData() != null) {
                TaskProgressMessage.TaskProgressData msgData = message.getData();
                progressData.setStatus(msgData.getStatus());
                progressData.setProgress(msgData.getProgress());
                progressData.setCurrentStep(msgData.getCurrentStep());
                progressData.setMessage(msgData.getMessage());
                progressData.setRecognizedText(msgData.getRecognizedText());
                progressData.setAiReply(msgData.getAiReply());
                progressData.setVoiceUrl(msgData.getVoiceUrl());
                progressData.setUserVoiceUrl(msgData.getUserVoiceUrl());
                progressData.setConversationId(msgData.getConversationId());
                progressData.setErrorCode(msgData.getErrorCode());
                progressData.setErrorMessage(msgData.getErrorMessage());
            }
            
            // 使用标准化WebSocket消息格式
            WebSocketMessage wsMessage;
            if ("TASK_COMPLETED".equals(message.getType())) {
                wsMessage = WebSocketMessage.taskCompleted(taskId, progressData);
            } else if ("TASK_FAILED".equals(message.getType())) {
                wsMessage = WebSocketMessage.taskFailed(taskId, progressData);
            } else {
                wsMessage = WebSocketMessage.progressUpdate(taskId, progressData);
            }
            wsMessage.setUserId(userId);
            
            // 转换为JSON字符串
            String jsonMessage = objectMapper.writeValueAsString(wsMessage);
            
            // 添加详细日志
            log.info("📤 准备发送WebSocket消息:");
            log.info("📤 任务ID: {}, 用户ID: {}", taskId, userId);
            log.info("📤 消息类型: {}", wsMessage.getType());
            log.info("📤 消息内容: {}", jsonMessage);
            log.info("📤 消息长度: {}", jsonMessage.length());
            
            // 检查用户会话状态
            log.info("🔍 查找用户WebSocket会话: userId={}, 总用户连接数={}", userId, userSessions.size());
            log.info("🔍 当前所有用户连接: {}", userSessions.keySet());
            
            WebSocketSession session = userSessions.get(userId);
            
            if (session == null) {
                log.error("❌ 用户WebSocket会话为空，无法发送消息: userId={}, taskId={}", userId, taskId);
                log.error("❌ 可能的原因: 1) 用户未连接 2) 连接已断开 3) userId错误");
                log.error("❌ 当前用户连接详情:");
                userSessions.forEach((key, value) -> {
                    log.error("   - 用户ID: {}, sessionId: {}, 开启状态: {}", 
                        key, value.getId(), value.isOpen());
                });
                return;
            }
            
            if (!session.isOpen()) {
                log.error("❌ 用户WebSocket会话已关闭，无法发送消息: userId={}, taskId={}, sessionId={}", 
                    userId, taskId, session.getId());
                // 清理无效会话
                userSessions.remove(userId);
                log.info("🧹 已清理无效用户WebSocket会话: userId={}", userId);
                return;
            }
            
            // 会话正常，发送消息
            session.sendMessage(new TextMessage(jsonMessage));
            log.info("✅ WebSocket消息发送成功: userId={}, taskId={}, sessionId={}", userId, taskId, session.getId());
            
        } catch (Exception e) {
            log.error("❌ 发送WebSocket消息失败: {}", taskId, e);
        }
    }
    
    /**
     * 从URI中提取用户ID
     */
    private String extractUserIdFromUri(URI uri) {
        String path = uri.getPath();
        // URI格式: /ws/voice-task/user/{userId}
        String[] segments = path.split("/");
        return segments[segments.length - 1]; // 获取最后一段作为userId
    }
    
    /**
     * 发送连接状态消息
     */
    private void sendConnectionMessage(String userId, String type, String message) {
        try {
            // 使用标准化消息格式
            WebSocketMessage wsMessage = WebSocketMessage.connected(userId, message);
            String jsonMessage = objectMapper.writeValueAsString(wsMessage);
            
            WebSocketSession session = userSessions.get(userId);
            if (session != null && session.isOpen()) {
                session.sendMessage(new TextMessage(jsonMessage));
                log.info("✅ 连接状态消息发送成功: userId={}, type={}", userId, type);
            }
        } catch (Exception e) {
            log.error("❌ 发送连接状态消息失败: userId={}", userId, e);
        }
    }
    
    /**
     * 获取用户会话状态信息（用于调试）
     */
    public String getUserSessionInfo(String userId) {
        WebSocketSession session = userSessions.get(userId);
        if (session == null) {
            return String.format("用户会话不存在: userId=%s, 总用户连接数=%d, 所有用户连接=%s", 
                userId, userSessions.size(), userSessions.keySet());
        }
        return String.format("用户会话存在: userId=%s, sessionId=%s, 开启状态=%s, URI=%s", 
            userId, session.getId(), session.isOpen(), session.getUri());
    }
    
    /**
     * 获取所有活跃会话（已废弃，使用getAllActiveUserSessions）
     */
    @Deprecated
    public Map<String, String> getAllActiveSessions() {
        return getAllActiveUserSessionsInfo();
    }
    
    /**
     * 检查并发送现有任务状态（在WebSocket连接建立后）
     */
    private void checkAndSendExistingTaskStatus(String taskId) {
        log.info("🔍 检查任务状态: taskId={}", taskId);
        // 这里可以添加查询任务状态的逻辑，如果任务已完成则发送完成消息
        // 由于需要依赖数据库查询，这里仅记录日志
        // 实际的任务状态同步由 TaskProgressService 处理
    }
    
    /**
     * 检查用户是否有活跃会话
     * @param userId 用户ID
     * @return 是否存在活跃会话
     */
    public boolean hasActiveUserSession(String userId) {
        WebSocketSession session = userSessions.get(userId);
        return session != null && session.isOpen();
    }
    
    /**
     * 获取活跃用户连接数量
     */
    public int getActiveUserSessionCount() {
        // 清理无效会话
        cleanupInactiveUserSessions();
        return userSessions.size();
    }
    
    /**
     * 清理无效的用户WebSocket会话
     */
    private void cleanupInactiveUserSessions() {
        int originalSize = userSessions.size();
        userSessions.entrySet().removeIf(entry -> {
            WebSocketSession session = entry.getValue();
            if (!session.isOpen()) {
                log.info("🧹 清理无效用户会话: userId={}, sessionId={}", entry.getKey(), session.getId());
                return true; // 移除
            }
            return false; // 保留
        });
        
        int removedCount = originalSize - userSessions.size();
        if (removedCount > 0) {
            log.info("🧹 已清理 {} 个无效用户会话，剩余 {} 个活跃用户连接", removedCount, userSessions.size());
        }
    }
    
    /**
     * 获取所有活跃用户会话
     */
    public Map<String, WebSocketSession> getAllActiveUserSessions() {
        cleanupInactiveUserSessions();
        return new HashMap<>(userSessions);
    }
    
    /**
     * 获取所有活跃用户会话信息（用于调试）
     */
    public Map<String, String> getAllActiveUserSessionsInfo() {
        Map<String, String> activeSessionsInfo = new HashMap<>();
        userSessions.forEach((userId, session) -> {
            activeSessionsInfo.put(userId, 
                String.format("sessionId=%s, isOpen=%s", session.getId(), session.isOpen()));
        });
        return activeSessionsInfo;
    }
    
    /**
     * 强制断开用户连接
     */
    public boolean disconnectUser(String userId) {
        try {
            WebSocketSession session = userSessions.get(userId);
            if (session != null && session.isOpen()) {
                session.close();
                userSessions.remove(userId);
                log.info("🔌 强制断开用户连接: userId={}", userId);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("❌ 强制断开用户连接失败: userId={}", userId, e);
            return false;
        }
    }
}
